#include <gtest/gtest.h>
#include <boost/scoped_ptr.hpp>

#include "NetFrameImplFactory.h"
#include "Interface.h"
#include "Channel.h"
#include "ChannelHandlerAdapter.h"
#include "Client.h"
#include "Service.h"



using namespace frame;

TEST(MainTest, structure){
    auto factory = NetFrameImplFactory::instance().create(MOCK);

    const char * remoteIp = "127.0.0.1";
    int remotePort = 1234;

    IService::Ptr service(new Service(factory));

    IClient::Ptr client = std::make_shared<Client>(service, std::make_shared<ChannelHandlerAdapter>());
    service->add(client);
    ASSERT_EQ(1, service->size());

    service->start(); 
    ASSERT_TRUE(client->isOpen());

    service->run(); //running it 

    service->remove(client->getId());
    ASSERT_EQ(0, service->size());

    service->stop();
}

TEST(MainTest, oneClientManyChannel){
    auto factory = NetFrameImplFactory::instance().create(MOCK);

    const char * remoteIp = "127.0.0.1";
    int remotePort = 1234;
    auto channelHandler = std::make_shared<ChannelHandlerAdapter>();

    IService::Ptr service(new Service(factory));

    IClient::Ptr client = std::make_shared<Client>(service, channelHandler);
    ASSERT_TRUE(client->getDefaultChannelHandlerAdapter() == channelHandler);
    service->add(client); 

    service->start(); 
    ASSERT_TRUE(client->isOpen());
    
    //Channe 1 : use default ReadHandler for new Channel
    IChannel::Ptr channel(client->connect(remoteIp, remotePort)); 
    //TODO: ASSERT_EQ(channelHandler, channel->getHandler());
    ASSERT_FALSE(channel->isConnected());
    ASSERT_FALSE(channel->isOpen());

    //Channel 2 use other IChannelHandlerAdapter for new Channel
    IChannelHandlerAdapter::Ptr channelHandler2 = std::make_shared<ChannelHandlerAdapter>();
    IChannel::Ptr channel2 = client->connect(remoteIp, remotePort, channelHandler2);
    //TODO: ASSERT_EQ(channelHandler2, channel2->getHandler());
    ASSERT_FALSE(channel2->isOpen());
    ASSERT_FALSE(channel->isConnected());

    //Write-Read
    channel->write("hello world");
    channel2->write("hello world");

    //Disconnect
    channel->disconnect();
    ASSERT_FALSE(channel->isOpen());

    channel2->disconnect();
    ASSERT_FALSE(channel2->isOpen());

    service->run();     // wait ????

    service->stop();    // close all runobjects
}
